package com.shkco.xbjcc.service.impl;

import com.shkco.exception.GlobalExceptionCode;
import com.shkco.utils.AssertUtil;
import com.shkco.utils.StrUtils;
import com.shkco.utils.VerifyCodeUtils;
import com.shkco.xbjcc.constants.RedisSmsConstants;
import com.shkco.xbjcc.domain.MessageSms;
import com.shkco.xbjcc.domain.Shielding;
import com.shkco.xbjcc.domain.UserIntegral;
import com.shkco.xbjcc.dto.SmsCodeDto;
import com.shkco.xbjcc.dto.SmsDto;
import com.shkco.xbjcc.feign.UserService;
import com.shkco.xbjcc.mapper.ShieldingMapper;
import com.shkco.xbjcc.properties.RedisSmsRegisterProperties;
import com.shkco.xbjcc.service.IMessageSmsService;
import com.shkco.xbjcc.service.IVerifyCodeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private IMessageSmsService messageSmsService;

    @Autowired
    private RedisSmsRegisterProperties redisSmsRegisterProperties;

    @Autowired
    private ShieldingMapper shieldingMapper;

    @Override
    public String getImgCode(String key) {
        //产生验证码
        String code = VerifyCodeUtils.generateVerifyCode(4);
        //存放redis
        redisTemplate.opsForValue().set(key, code,5, TimeUnit.MINUTES);
        return VerifyCodeUtils.verifyCode(140, 40, code);
    }

    @Override
    public void sendSmsCode(SmsCodeDto smsCodeDto) {
        String imageCode = smsCodeDto.getImageCode();
        String mobile = smsCodeDto.getMobile();
        String imageCodeKey = smsCodeDto.getImageCodeKey();

        Shielding shielding = shieldingMapper.findByPhone(mobile);
        AssertUtil.isNull(shielding,GlobalExceptionCode.USER_SHIELDING);
        AssertUtil.isPhone(mobile,GlobalExceptionCode.PHONE_IS_NULL);
        boolean b = StringUtils.isEmpty(imageCode);
        AssertUtil.isFalse(b,GlobalExceptionCode.IMGCODE_IS_NULL);

        Object o = redisTemplate.opsForValue().get(imageCodeKey);

        AssertUtil.isNotNull(o,GlobalExceptionCode.IMGCOD_EXPIRED);

        boolean b1 = o.toString().equalsIgnoreCase(imageCode);
        AssertUtil.isTrue(b1,GlobalExceptionCode.IMGCOD_MISTAKE);

        // 获取手机验证码，判断是否过期
        String rediskey = String.format(RedisSmsConstants.REDIS_REGISTER_PHONE_KEY, mobile);
        Object obj = redisTemplate.opsForValue().get(rediskey);
        String smsCode = null;
        if (obj == null){
            // 过期了或者没有，通过工具类生成
            smsCode = StrUtils.getRandomString(redisSmsRegisterProperties.getCodesize());
        } else {
            // 没有过期,获取时间戳
            SmsDto smsDto = (SmsDto)obj;
            // 判断是否过重发时间
            boolean b2 = System.currentTimeMillis() - smsDto.getTime() < redisSmsRegisterProperties.getInterval();
            AssertUtil.isFalse(b2,GlobalExceptionCode.OPERATE_FREQUENTLY);

            // 如果过了重发时间,使用上面的验证码
            smsCode = smsDto.getCode();
        }
        // 保存到redis  重新设置3分钟过期
        SmsDto smsDto = new SmsDto(smsCode,System.currentTimeMillis());
        redisTemplate.opsForValue().set(rediskey,smsDto,redisSmsRegisterProperties.getExpiredtime(),TimeUnit.SECONDS);

        sendMessageSms(smsCode);

    }

    private void sendMessageSms(String smsCode) {
        // 存储消息
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(redisSmsRegisterProperties.getTitle());
        String content = String.format(redisSmsRegisterProperties.getContent(), smsCode);
        messageSms.setContent(content);
        messageSms.setSendTime(new Date());
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getRemoteAddr();
        messageSms.setIp(ip);
        messageSmsService.insert(messageSms);
        // 调用工具类发送短信
        log.info(content);
    }

}
